﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using XNALibrary.ZCAMERA;

namespace XNALibrary.OmniCamera
{
    public class OmniCamera : ICamera
    {
        public List<IWatchable> targets;
        public Vector3 offset;

        protected float fieldOfView;
        protected float aspectRatio;
        protected float nearPlane;
        protected float farPlane;

        public OmniCamera()
        {
            fieldOfView = MathHelper.ToRadians(45.0f);
            aspectRatio = 1.0f;
            nearPlane = 1.0f;
            farPlane = 10000.0f;

            targets = new List<IWatchable>();
        }

        #region ICamera Members

        public Microsoft.Xna.Framework.Matrix View
        {
            get 
            {
                Vector3 center = CalcCenterPt();
                float radius = CalcRadius(center);
                float distToVeiw = radius / (float)Math.Sin(fieldOfView / 2);
                if (distToVeiw < 25) distToVeiw = 25;
                offset = new Vector3(1, 1, 0);
                offset.Normalize();
                offset = center + distToVeiw * offset;

                return Matrix.CreateLookAt(offset, center, Vector3.Up);
            }
        }

        private Vector3 CalcCenterPt()
        {
            Vector3 sum = Vector3.Zero;
            foreach (IWatchable iw in targets)
                sum += iw.GetPosition();

            return sum / targets.Count;
        }

        private float CalcRadius(Vector3 center)
        {
            float radius = 0, dist;
            foreach (IWatchable iw in targets)
            {
                dist = Vector3.Distance(iw.GetPosition(), center);
                if (dist > radius)
                    radius = dist;
            }
            return radius;
        }

        public Microsoft.Xna.Framework.Matrix Projection
        {
            get
            {
                return Matrix.CreatePerspectiveFieldOfView(fieldOfView, aspectRatio,
                        nearPlane, farPlane);
            }
        }

        public string GetGuide()
        {
            return "";
        }

        public string GetViewName()
        {
            return "OmniCam sees everything";
        }

        public void Update(Microsoft.Xna.Framework.GameTime gt)
        {
        }

        public Vector3 GetPosition()
        {
            return offset;
        }

        #endregion
    }
}
